package com.wu.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wu.client.constant.*;

import com.wu.client.dao.redis.Likes;
import com.wu.client.service.AlbumService;
import com.wu.client.service.RelationshipService;
import com.wu.client.service.UserLikesService;
import com.wu.client.utils.ListUtil;
import com.wu.client.utils.PageRespUtil;
import com.wu.client.vo.req.album.AlbumReq;
import com.wu.client.vo.res.PageResp;
import com.wu.client.vo.res.album.AlbumBaseResp;
import com.wu.client.vo.res.album.AlbumDetailResp;
import com.wu.client.vo.res.album.AlbumResp;
import com.wu.mysql.entiy.AlbumDO;
import com.wu.mysql.entiy.ArtistDO;
import com.wu.mysql.entiy.RelationshipDO;
import com.wu.mysql.mapper.AlbumMapper;
import com.wu.mysql.mapper.ArtistMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class AlbumServiceImpl extends ServiceImpl<AlbumMapper, AlbumDO> implements AlbumService {
    private final RelationshipService relationshipService;
    private final ArtistMapper artistMapper;
    private final UserLikesService userLikesService;
    private final StringRedisTemplate stringRedisTemplate;
    @Override
    public AlbumDetailResp getAlbumDetail(Long id, Long userId) {
        AlbumDO albumDO = query().eq("id", id).one();
        AlbumDetailResp albumDetailResp = new AlbumDetailResp();
        BeanUtils.copyProperties(albumDO,albumDetailResp);
        RelationShipTypeEnum artistAlbum = RelationShipTypeEnum.ARTIST_ALBUM;
        List<RelationshipDO> relationshipDOS = relationshipService.getByTargetId(artistAlbum, id);
        if (CollectionUtil.isNotEmpty(relationshipDOS)){
            List<Long> artistIds = relationshipDOS.stream().map(RelationshipDO::getSourceId).toList();
            String artistNames = artistMapper.selectBatchIds(artistIds).stream().map(ArtistDO::getName).collect(Collectors.joining("/"));
            albumDetailResp.setArtists(artistNames);
        }
        Map<Long, Likes> longLikesMap = userLikesService.checkUserIfLike(ResTypeEnum.ALBUM, userId, List.of(albumDetailResp.getId()));
        if (CollectionUtil.isNotEmpty(longLikesMap)){
            Likes like = longLikesMap.get(albumDetailResp.getId());
            albumDetailResp.setIsLiked(like.getIsLiked());
            albumDetailResp.setLikesCount(like.getCount());
        }
        albumDetailResp.setGenre(AlbumGenreEnum.getGenreByCode(albumDO.getGenre()));
        albumDetailResp.setType(AlbumTypeEnum.getTypeByCode(albumDO.getType()));
        return albumDetailResp;
    }

    @Override
    public PageResp<AlbumBaseResp> getAlbums(AlbumReq params) {
        PageResp<AlbumBaseResp> pageResp = new PageResp<>();
        Page<AlbumDO> page =new Page<>(params.getPage(), params.getLimit());
        Page<AlbumDO> albumDOPage = query().eq(ObjectUtil.isNotNull(params.getGenre()), "genre", params.getGenre())
                .eq(ObjectUtil.isNotNull(params.getLanguage()), "language", params.getLanguage())
                .eq(ObjectUtil.isNotNull(params.getRegion()), "region", params.getRegion())
                .page(page);
        List<AlbumDO> records = albumDOPage.getRecords();
        List<AlbumBaseResp> items = BeanUtil.copyToList(records, AlbumBaseResp.class);

        List<Long> albumIds = items.stream().map(AlbumBaseResp::getId).toList();
        LambdaQueryWrapper<RelationshipDO> relationshipDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
        relationshipDOLambdaQueryWrapper.eq(RelationshipDO::getRelationshipType,RelationShipTypeEnum.ARTIST_ALBUM.getCode())
                .in(RelationshipDO::getTargetId,albumIds);
        List<RelationshipDO> relationshipDOS = relationshipService.list(relationshipDOLambdaQueryWrapper);

        Map<Long, List<RelationshipDO>> map = relationshipDOS.stream().collect(Collectors.groupingBy(RelationshipDO::getTargetId));
        List<Long> artisIds = relationshipDOS.stream().map(RelationshipDO::getSourceId).toList();
        List<ArtistDO> artistDOS = artistMapper.selectBatchIds(artisIds);
        Map<Long, ArtistDO> artistMap = artistDOS.stream().collect(Collectors.toMap(ArtistDO::getId,a->a));
        for (AlbumBaseResp item : items) {
            Long id = item.getId();
            List<RelationshipDO> relationshipDOList = map.get(id);
            // 使用Stream优化此部分
            String artistsNames = relationshipDOList.stream()
                    .map(relationshipDO -> artistMap.get(relationshipDO.getSourceId()))
                    .filter(Objects::nonNull) // 避免null值的情况
                    .map(ArtistDO::getName)
                    .collect(Collectors.joining("/")); // 使用"/"连接
            item.setArtists(artistsNames);
        }
        pageResp.setItems(items);
        pageResp.setPage(Math.toIntExact(albumDOPage.getCurrent()));
        pageResp.setTotal(albumDOPage.getTotal());
        pageResp.setLimit(Math.toIntExact(albumDOPage.getPages()));
        return pageResp;
    }





    @Override
    public PageResp<AlbumBaseResp> getArtistAlbum(Long artistId, Long userId, Integer page, Integer limit) {
        Page<RelationshipDO> relationshipDOPage = relationshipService.getPageBySourceId(RelationShipTypeEnum.ARTIST_ALBUM, artistId, page, limit);
        List<RelationshipDO> records = relationshipDOPage.getRecords();
        if (CollectionUtil.isEmpty(records)){
            return new PageResp<>();
        }
        List<Long> albumIds = records.stream().map(RelationshipDO::getSourceId).toList();
        List<AlbumDO> albumDOS = this.listByIds(albumIds);
        List<AlbumBaseResp> baseRespList = BeanUtil.copyToList(albumDOS, AlbumBaseResp.class);
        PageRespUtil.buildPageResp(page,limit,relationshipDOPage.getTotal(),baseRespList);
        return PageRespUtil.buildPageResp(page,limit,relationshipDOPage.getTotal(),baseRespList);
    }

    @Override
    public PageResp<AlbumResp> getUserFavoritesAlbums(Long userId, Integer page, Integer limit) {
        String userLikesRedisKey = RedisKeyConstant.getUserLikesRedisKey(ResTypeEnum.ALBUM.getCode(), userId);
        Set<String> albumIds = stringRedisTemplate.opsForSet().members(userLikesRedisKey);
        if (CollectionUtil.isNotEmpty(albumIds)){
            List<Long> ids = albumIds.stream().map(Long::parseLong).toList();
            long count  = ids.size();
            ids = ListUtil.subListInPage(ids, page, limit);
            List<AlbumDO> albumDOS = this.listByIds(ids);
            if (CollectionUtil.isNotEmpty(albumDOS)){
                List<AlbumResp> albumRespList = albumDOS.stream().map(albumDO -> {
                    AlbumResp albumResp= BeanUtil.toBean(albumDO, AlbumResp.class);
                    String artisName = relationshipService.getArtisName(albumDO.getId(), RelationShipTypeEnum.ALBUM_SONG);
                    albumResp.setArtists(artisName);

                    return albumResp;
                }).toList();
                return PageRespUtil.buildPageResp(page,limit,count, albumRespList);
            }

        }
        return new PageResp<>();
    }

}
